home *** CD-ROM | disk | FTP | other *** search
-
-
- /*****************************************************************************/
- /* */
- /* AmigaAMP Wide Spectrometer Plugin 1.3 */
- /* */
- /* Written August 1999 by Thomas Wenzel */
- /* */
- /*****************************************************************************/
- /* */
- /* This is an example how to write your own AmigaAMP visualisation plugin */
- /* To make it as easy as possible all plugins are normal AmigaDOS */
- /* executables which can be launched and stopped at any time. */
- /* */
- /* This sourcecode and executable are free for non-commercial use only! */
- /* */
- /*****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <math.h>
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/intuition.h>
- #include <proto/graphics.h>
-
- #include <dos/dostags.h>
- #include <graphics/gfxbase.h>
-
- #include "TrackInfo.h" // new in v1.2
-
- WORD PluginInit(void);
- void PluginExit(void);
- void PluginLoop(void);
- void ShowRequester(char *Text, char *Button);
-
- /***************************************************************************/
- /* This is the global variables section. Don't change anything here unless */
- /* you know what you're doing! */
- /***************************************************************************/
-
- BYTE PluginSignal, InfoSignal;
- ULONG PluginMask, InfoMask;
- WORD Accepted;
- struct Process *PluginTask;
- struct MsgPort *PluginMP;
- struct MsgPort *PluginRP;
- struct TrackInfo *tinfo; /* New: v1.2 */
-
- UWORD *PluginRawL;
- UWORD *PluginRawR;
- WORD *PluginSamples;
- UWORD *SpecRawL;
- UWORD *SpecRawR;
- WORD *SampleRaw;
-
- struct PluginMessage {
- struct Message msg;
- ULONG PluginMask;
- struct Process *PluginTask;
- UWORD **SpecRawL;
- UWORD **SpecRawR;
- WORD Accepted; /* v1.3: Don't use BOOL any more because */
- WORD reserved0; /* it causes alignment problems! */
-
- /* All data beyond this point is new for v1.2. */
- /* AmigaAMP v2.5 and up will detect this new data and act accordingly. */
- /* Older versions of AmigaAMP will simply ignore it. */
-
- ULONG InfoMask;
- struct TrackInfo **tinfo;
- ULONG reserved; // always set to 0
-
- /* All data beyond this point is new for v1.3. */
- /* AmigaAMP v2.7 and up will detect this new data and act accordingly. */
- /* Older versions of AmigaAMP will simply ignore it. */
-
- WORD **SampleRaw;
- };
-
- /***************************************************************************/
- /* This is the main part. Again, don't change anything here if you haven't */
- /* got a very good reason to do so! */
- /***************************************************************************/
-
- void main(void) {
- struct PluginMessage *PluginMsg;
- struct PluginMessage *ReplyMsg;
-
- /* Allocate all user resources */
- if(PluginInit()) {
- /* Check if a plugin capable instance of AmigaAMP is running */
- if(PluginMP=FindPort("AmigaAMP plugin port")) {
- /* Allocate a sigbit for receiving signals FROM AmigaAMP */
- PluginSignal = AllocSignal(-1);
- InfoSignal = AllocSignal(-1); /* New: v1.2 */
- PluginTask = (struct Process *)FindTask(NULL);
-
- if(PluginSignal != -1 && InfoSignal != -1) {
- PluginMask = 1L << PluginSignal;
- InfoMask = 1L << InfoSignal;
-
- /* Allocate a message and reply port for sending messages TO AmigaAMP */
- PluginMsg=AllocVec(sizeof(struct PluginMessage), MEMF_PUBLIC|MEMF_CLEAR);
- PluginRP=CreatePort(0,0);
-
- /* Tell AmigaAMP all the details it needs to know */
- PluginMsg->msg.mn_Node.ln_Type = NT_MESSAGE;
- PluginMsg->msg.mn_Length = sizeof(struct PluginMessage);
- PluginMsg->msg.mn_ReplyPort = PluginRP;
- PluginMsg->PluginMask = PluginMask;
- PluginMsg->PluginTask = PluginTask;
- PluginMsg->SpecRawL = &SpecRawL;
- PluginMsg->SpecRawR = &SpecRawR;
- PluginMsg->InfoMask = InfoMask; /* New: v1.2 */
- PluginMsg->tinfo = &tinfo; /* New: v1.2 */
- PluginMsg->reserved = 0; /* New: v1.2 */
- PluginMsg->SampleRaw = &SampleRaw; /* New: v1.3 */
- PutMsg(PluginMP, (struct Message *)PluginMsg);
- /* Wait for a reply */
- WaitPort(PluginRP);
- /* Let's see if AmigaAMP accepted our registration attempt */
- if(ReplyMsg = (struct PluginMessage *)GetMsg(PluginRP)) Accepted=ReplyMsg->Accepted;
- else Accepted=FALSE;
-
- if(Accepted) {
- /* If it did, start the plugin loop */
- PluginLoop();
-
- /* Tell AmigaAMP that this plugin is going down */
- PluginMsg->PluginMask = NULL;
- PluginMsg->PluginTask = NULL;
- PluginMsg->SpecRawL = NULL;
- PluginMsg->SpecRawR = NULL;
- PluginMsg->InfoMask = NULL; /* New: v1.2 */
- PluginMsg->tinfo = NULL; /* New: v1.2 */
- PluginMsg->SampleRaw = NULL; /* New: v1.3 */
- PutMsg(PluginMP, (struct Message *)PluginMsg);
- /* Wait for confirmation before going on! */
- WaitPort(PluginRP);
- GetMsg(PluginRP);
- /* Now that AmigaAMP knows that we're gone, we can quit */
- }
- else {
- /* If AmigaAMP didn't accept us, tell the user about it */
- ShowRequester("Plugin rejected by AmigaAMP!\nPerhaps there's another one running.", "Abort");
- }
-
- /* Free all resources */
- FreeVec(PluginMsg);
- DeletePort(PluginRP);
- if(PluginSignal != -1) FreeSignal(PluginSignal);
- if(InfoSignal != -1) FreeSignal(InfoSignal);
- }
- else {
- ShowRequester("Signal allocation failure!", "Abort");
- }
- }
- else {
- ShowRequester("Could not find message port!\nAmigaAMP probably not running.", "Abort");
- }
- }
- else {
- ShowRequester("Plugin initialisation failed!", "Ok");
- }
- /* Free all user resources */
- PluginExit();
- }
-
- /*****************************************************************************/
- /* Ok, now for the individual plugin sourcecode. Everything below should be */
- /* changed to your needs. */
- /* Just like before, we start with the global variables section */
- /*****************************************************************************/
-
- /* Turn on some code optimizations */
- #define OPTIMIZED
- #define STEP 2
-
- const char VersionString[]="\0$VER: WideSpectrometer 1.2 (27.01.99)";
-
- struct Screen *PluginScreen = NULL;
- struct Window *PluginWin = NULL;
- struct RastPort *rp;
- struct RastPort *tmprp;
-
- ULONG WinMask;
-
- UBYTE Pixel[132][512];
- UBYTE Colour[128];
- UBYTE ScopePen;
-
- UBYTE PeakL[256];
- UBYTE PeakR[256];
- UBYTE MaxL[256];
- UBYTE MaxR[256];
-
- UWORD offx, offy;
-
- char InfoLine[256];
-
- /****************************************************************************/
- /* This function will be called once when the plugin is started. You should */
- /* allocate all needed resources here. Return TRUE if all went well. */
- /****************************************************************************/
-
- WORD PluginInit(void) {
- long i;
-
- if(GfxBase->LibNode.lib_Version < 39) {
- ShowRequester("This plugin requires AmigaOS 3.0 or greater!", "Abort");
- return(FALSE);
- }
-
- if(PluginWin=OpenWindowTags(NULL,
- WA_Left, 20,
- WA_Top, 20,
- WA_InnerWidth, 512,
- WA_InnerHeight, 132,
- WA_Title, "AmigaAMP Wide Spectrometer Plugin 1.2",
- WA_DragBar, TRUE,
- WA_DepthGadget, TRUE,
- WA_CloseGadget, TRUE,
- WA_IDCMP, IDCMP_CLOSEWINDOW,
- TAG_END)) {
- WinMask = 1L << PluginWin->UserPort->mp_SigBit;
-
- rp=PluginWin->RPort;
-
- /* This is an attempt to make it OS3.0 compatible. */
- /* Don't blame me if it doesn't work :-) */
- tmprp=(struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_CHIP|MEMF_CLEAR);
- CopyMem(rp, tmprp, sizeof(struct RastPort));
- tmprp->Layer = NULL;
- tmprp->BitMap = AllocBitMap((((512+15)>>4)<<1), 1, 8, BMF_CLEAR|BMF_DISPLAYABLE, rp->BitMap);
-
-
- offx = PluginWin->BorderLeft;
- offy = PluginWin->BorderTop;
-
- if(PluginScreen=LockPubScreen(NULL)) {
- for(i=0; i<64; i++) {
- Colour[i] = ObtainBestPen(PluginScreen->ViewPort.ColorMap, 0xFFFFFFFF, i * 0x4000000, 0, NULL);
- Colour[i+64] = ObtainBestPen(PluginScreen->ViewPort.ColorMap, 0xFFFFFFFF, 0xFFFFFFFF, i * 0x4000000, NULL);
- }
- ScopePen = ObtainBestPen(PluginScreen->ViewPort.ColorMap, 0x22222222, 0xFFFFFFFF, 0x2222222, NULL);
-
- for(i=0; i<256; i++) {
- PeakL[i]=0;
- PeakR[i]=0;
- MaxL[i]=0;
- MaxR[i]=0;
- }
- return(TRUE);
- }
- }
- return(FALSE);
- }
-
- /******************************************************************************/
- /* This function will be called when the plugin is shut down. You should free */
- /* all previously allocated resources here. */
- /******************************************************************************/
-
- void PluginExit(void) {
- long i;
-
- if(PluginScreen) for(i=0; i<128; i++) {
- ReleasePen(PluginScreen->ViewPort.ColorMap, Colour[i]);
- }
- ReleasePen(PluginScreen->ViewPort.ColorMap, ScopePen);
-
-
- if(tmprp) {
- if(tmprp->BitMap) FreeBitMap(tmprp->BitMap);
- FreeVec(tmprp);
- }
- if(PluginWin) CloseWindow(PluginWin);
- if(PluginScreen) UnlockPubScreen(NULL, PluginScreen);
- }
-
- /*******************************************************************************/
- /* This is the main Plugin Loop. It will receive a signal matching PluginMask */
- /* each time new spectral data is ready. The data is stored in two arrays, */
- /* UWORD SpecRawL[512] and UWORD SpecRawR[512]. The scale is logarithmic, i.e. */
- /* 0 means below -96dB, 65535 means 0dB. Another array SampleRaw[1024] holds */
- /* the current waveform. This array is not divided into left and right channel */
- /* but contains interleaved stereo data, 16-bit signed just like in an AIFF or */
- /* in a CDDA file. */
- /* No matter how long it takes until your plugin actually processes the data, */
- /* the memory referenced by the array pointers always remains valid! */
- /* */
- /* Your plugin loop MUST quit when it receives SIGBREAKF_CTRL_C. If you've */
- /* opened a window you should react to the close gadget as well. For full */
- /* screen plugins I strongly recommend checking the ESC key. */
- /*******************************************************************************/
-
- void PluginLoop(void) {
- ULONG *PixelL;
- UBYTE *ActPixel;
- ULONG Signals;
- LONG i,j,l;
- WORD Sample;
- UBYTE Value;
-
- for(;;) {
-
- /* Wait until there's something to do */
- Signals=Wait(SIGBREAKF_CTRL_C | PluginMask | WinMask | InfoMask);
-
- /* Break received -> quit at once! */
- if(Signals & SIGBREAKF_CTRL_C) break;
-
- /* Window close gadget hit -> quit as well! */
- if(Signals & WinMask) {
- struct IntuiMessage *imsg;
- WORD done=0;
-
- while(imsg=(struct IntuiMessage *)GetMsg(PluginWin->UserPort)) {
- if(imsg->Class == IDCMP_CLOSEWINDOW) done=1;
- }
- if(done) break;
- }
-
- /* New data has arrived! */
- if(Signals & PluginMask) {
-
- /* Initialize the pixel array */
- #ifdef OPTIMIZED
- PixelL = (ULONG*)Pixel;
- for(i=0; i<16896; i++) {
- *PixelL++ = 0x01010101;
- }
- #else
- for(i=0; i<512; i++) {
- for(j=0; j<132; j++) {
- Pixel[j][i]=1;
- }
- }
- #endif
-
- /* Make a backup of the data pointers */
- PluginRawL = SpecRawL;
- PluginRawR = SpecRawR;
- PluginSamples = SampleRaw; /* New: v1.3 */
-
- /* Process the spectral data of the left channel */
- for(i=1; i<256; i+=STEP) {
- /* Get the value of each spectral line to be drawn */
- /* The value ranges from 0 to 65535. Our window has */
- /* only room for 128 pixels so we need to scale it */
- /* down. */
- l=PluginRawL[512-(i<<1)]>>9;
-
- /* Set peak- and peak-hold-values */
- if(l>PeakL[i]) PeakL[i]=l;
- if(l>MaxL[i]) MaxL[i]=l;
-
- /* Draw the colourful line */
- #ifdef OPTIMIZED
- ActPixel=&Pixel[130][i];
- for(j=0; j<MaxL[i]; j++) {
- *ActPixel = Colour[j];
- ActPixel -= 512;
- }
- #else
- for(j=0; j<MaxL[i]; j++) {
- Pixel[130-j][i]=Colour[j];
- }
- #endif
-
- /* Draw the peak pixel */
- Pixel[130-PeakL[i]][i]=2;
-
- /* Draw the waveform pixel */
- Pixel[65-(SampleRaw[i<<1]>>9)][i]=ScopePen;
-
-
- /* Calculate the falloff of both peak and peak-hold */
- Value=PeakL[i];
- if(Value > 96) Value--;
- if(Value > 64) Value--;
- if(Value > 32) Value--;
- if(Value > 1) Value--;
- PeakL[i]=Value;
- Value=MaxL[i];
- if(Value > 96) Value-=4;
- if(Value > 64) Value-=4;
- if(Value > 32) Value-=4;
- if(Value > 4) Value-=4;
- if(Value > 1) Value-=1;
- MaxL[i]=Value;
- }
-
- /* Process the spectral data of the right channel */
- for(i=1; i<256; i+=STEP) {
- l=PluginRawR[i<<1]>>9;
- if(l>PeakR[i]) PeakR[i]=l;
- if(l>MaxR[i]) MaxR[i]=l;
-
- #ifdef OPTIMIZED
- ActPixel=&Pixel[130][256+i];
- for(j=0; j<MaxR[i]; j++) {
- *ActPixel = Colour[j];
- ActPixel -= 512;
- }
- #else
- for(j=0; j<MaxR[i]; j++) {
- Pixel[130-j][256+i]=Colour[j];
- }
- #endif
- Pixel[130-PeakR[i]][256+i]=2;
- Pixel[65-(SampleRaw[i<<1+1]>>9)][256+i]=ScopePen;
-
- Value=PeakR[i];
- if(Value > 96) Value--;
- if(Value > 64) Value--;
- if(Value > 32) Value--;
- if(Value > 1) Value--;
- PeakR[i]=Value;
- Value=MaxR[i];
- if(Value > 96) Value-=4;
- if(Value > 64) Value-=4;
- if(Value > 32) Value-=4;
- if(Value > 4) Value-=4;
- if(Value > 1) Value-=1;
- MaxR[i]=Value;
- }
-
- /* Draw the image (now uses WPA8 for OS3.0 compatibility) */
- // WriteChunkyPixels(rp, offx, offy, offx+511, offy+131, &Pixel[0][0], 512);
- WritePixelArray8(rp, offx, offy, offx+511, offy+131, &Pixel[0][0], tmprp);
- }
-
-
- /* New track info has arrived! */
- if(Signals & InfoMask) {
- if(tinfo) {
-
- /* process contents of tinfo here */
- /* see "TrackInfo.h" for details! */
-
- /* Example: Display the track info text */
- if(tinfo->TrackInfoText) {
- sprintf(InfoLine, "AmigaAMP: %s", tinfo->TrackInfoText);
- SetWindowTitles(PluginWin, InfoLine, "AmigaAMP Wide Spectrometer Plugin 1.3");
- }
- }
- }
- }
- }
-
- void ShowRequester(char *Text, char *Button) {
- struct EasyStruct Req;
-
- Req.es_Title = "AmigaAMP Plugin";
- Req.es_TextFormat = (UBYTE*)Text;
- Req.es_GadgetFormat = (UBYTE*)Button;
- EasyRequestArgs(NULL, &Req, NULL, NULL);
- }
-